package com.google.cbmgraph;

import com.google.cbmgraph.cell.CellFormat;
import com.google.cbmgraph.cell.DataMap;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.widget.Toast;
/**
 * This is the master class that draws everything. It's a Surfaceview, which allows
 * it to be run on a thread, as opposed to a clunkier way. The canvas is used to draw everything
 * 
 * @author lawlerr1
 *
 */
public class GraphMap extends SurfaceView implements SurfaceHolder.Callback {
	public static int cellSizeX = CellFormat.X;
	public static int cellSizeY = CellFormat.Y;
	private GraphViewThread graphThread;

	public Canvas canvas;
	
	public static final int xMaxCount=72;
	public static final int yMaxCount=100;	
	
	private int firstRow;
	private int lastRow;
	private int firstCol;
	private int lastCol;
	
	// Offset to the upper left corner of the map
	private int offsetX = 0;
	private int offsetY = 0;
	 
	// last touch point
	private int lastX = 0;
	private int lastY = 0;
	
	// name
	private String name = null;
	 
	private boolean inMotion = false;
	/**
	 * 
	 * @return theheight for the graph area
	 */
	private int getGraphHeight(){
		return getHeight()-140;
	}

	/**
	 * 
	 * @return the width for the graph area
	 */
	private int getGraphWidth(){
		return getWidth()-100;
	}
	/**
	 * Recalcualtes the borders
	 */	
	private void calculateBorders(){
		firstRow =offsetY/cellSizeY;
		lastRow = (int)Math.min(yMaxCount, firstRow+Math.floor(getGraphHeight()/cellSizeY)+2);
		firstCol = offsetX/cellSizeX;
		lastCol = (int)Math.min(xMaxCount, firstCol+Math.floor(getGraphWidth()/cellSizeX)+2);
	}
	/**
	 * Handle touch event on the map.
	 */
	@Override
	public boolean onTouchEvent(MotionEvent event) {

	    if (event.getAction() == MotionEvent.ACTION_DOWN) {
	        inMotion = false;
	        lastX = (int) event.getX();
	        lastY = (int) event.getY();
	    } else if (event.getAction() == MotionEvent.ACTION_MOVE) {
	        inMotion = true;
	        offsetX += lastX - (int) event.getX();
	        offsetY += lastY - (int) event.getY();
	        if (offsetX < 0) {
	            offsetX = 0;
	        } else if (offsetX > xMaxCount * cellSizeX - getGraphWidth()) {
	            offsetX = xMaxCount * cellSizeX - getGraphWidth();
	        }
	        if (offsetY < 0) {
	            offsetY = 0;
	        } else if (offsetY > yMaxCount * cellSizeY - getGraphHeight()) {
	            offsetY = yMaxCount * cellSizeY - getGraphHeight();
	        }
	        // store the last position
	        lastX = (int) event.getX();
	        lastY = (int) event.getY();
	        calculateBorders();
	    } else if (event.getAction() == MotionEvent.ACTION_UP) {
	        // touch released
	        if (!inMotion) {
	            // calculate the touched cell
	            int column = (int) Math.ceil((offsetX + event.getX()) / cellSizeX) - 1;
	            int row = (int) Math.ceil((offsetY + event.getY()) / cellSizeY) - 1;
	            Toast.makeText(getContext(), "Cell location: " + column + ", "+ row + " Next revision hopefully you can add an annotation here!", Toast.LENGTH_SHORT).show();
	            
	        }
	    }
	    return true;
	}

	// holds map data
	private DataMap myMap;
	/**
	 * creates map
	 * @param context
	 * @param name 
	 */
	public GraphMap(Context context, AttributeSet attributeSet){
		
		super(context);	
		myMap = new DataMap();
		
		getHolder().addCallback(this);
		
		graphThread = new GraphViewThread(this);
		
		setFocusable(true);
	}
	/**
	 * draw stuff on this canvas!
	 */
	@Override
	public void onDraw(Canvas canvas){
		
		canvas.drawColor(Color.BLACK);
		int y=0, x=0;
		int myI = 0;

		for (int i = firstRow; i < lastRow; i++){
			y = myI * cellSizeY;
			int myJ= 1;
			for (int j = firstCol; j < lastCol; j++)
			{
				x = myJ * cellSizeX;
				myMap.getNode(j,(100-i)).draw(canvas, x,y);
				myJ++;
			}
			myI++;
		}
		
		y = 0;
		x = 0;
		int myHeaderCounter=0;
		for (int j = firstRow; j < lastRow; j++){
			x = myHeaderCounter * cellSizeX;
			y = myHeaderCounter * cellSizeY; 
			int myOffset = 100 - firstRow;
			myMap.drawCoord(10,y, myOffset- myHeaderCounter, canvas);
			myHeaderCounter++;
		}
		myHeaderCounter=1;
		y = getGraphHeight()+100; 
		for (int j= firstCol; j< lastCol; j++){
			x = myHeaderCounter * cellSizeX;
			myMap.drawCoord(x,y, firstCol+myHeaderCounter-1, canvas);
			myHeaderCounter++;
		}
		if(name != null)
			myMap.drawCoord(x,y , name, canvas);
	}
	public void loadTitle(String newTitle){
		name = newTitle;
	}
/**
 * start running a thread for this when created
 */
	@Override
	public void surfaceCreated(SurfaceHolder holder){
		
		if(!graphThread.isAlive()){
			graphThread = new GraphViewThread(this);
		}
		graphThread.run = true;
		graphThread.start();
		calculateBorders();
	}
	/**
	 * if this is destroyed, finish running
	 */
	@Override
	public void surfaceDestroyed(SurfaceHolder holder){
		boolean retry = true;
		graphThread.run=false;
		while(retry){
			try {
				graphThread.join();
				retry = false;
			} catch (InterruptedException e) {
				// nothing to do here
			}
		}
	}
/**
 * nothing to see here
 */
	@Override
	public void surfaceChanged(SurfaceHolder arg0, int arg1, int arg2, int arg3) {} 
	 
}
